#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include "ota.h"
#include "../utils/log.h"

// 全局变量
static bool g_is_initialized = false;
static bool g_is_running = false;
static bool g_update_in_progress = false;
static pthread_mutex_t g_ota_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_ota_cond = PTHREAD_COND_INITIALIZER;
static ota_info_t g_current_ota_info;
static ota_progress_t g_ota_progress;
static ota_event_cb g_event_callback = NULL;
static void *g_callback_user_data = NULL;
static char g_current_version[] = "1.0.0";

// 模拟OTA检查更新
static int mock_check_update(ota_info_t *info)
{
    // 模拟有新版本
    if (info) {
        strncpy(info->version, "1.0.1", sizeof(info->version) - 1);
        strncpy(info->url, "http://example.com/firmware/drone_v1.0.1.bin", sizeof(info->url) - 1);
        info->file_size = 5 * 1024 * 1024; // 5MB
        // 确保字符串正确终止
        strncpy(info->md5, "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", sizeof(info->md5) - 1);
        info->md5[sizeof(info->md5) - 1] = '\0';
        strncpy(info->description, "修复了一些问题，优化了性能", sizeof(info->description) - 1);
    }
    return 1; // 有更新
}

// 模拟下载固件
static int mock_download_firmware(const char *url, uint64_t *downloaded_size, uint64_t total_size)
{
    (void)url; // 消除未使用参数警告
    
    // 模拟下载过程
    *downloaded_size = 0;
    while (*downloaded_size < total_size) {
        // 检查是否取消
        pthread_mutex_lock(&g_ota_mutex);
        if (!g_update_in_progress) {
            pthread_mutex_unlock(&g_ota_mutex);
            return OTA_ERROR_CANCEL;
        }
        pthread_mutex_unlock(&g_ota_mutex);
        
        // 模拟下载速度
        *downloaded_size += 1024 * 512; // 每次下载512KB
        if (*downloaded_size > total_size) {
            *downloaded_size = total_size;
        }
        
        // 更新进度
        pthread_mutex_lock(&g_ota_mutex);
        g_ota_progress.downloaded_size = *downloaded_size;
        pthread_mutex_unlock(&g_ota_mutex);
        
        LOG_INFO("OTA下载进度: %llu/%llu bytes (%.1f%%)", 
                 *downloaded_size, total_size, 
                 (*downloaded_size * 100.0) / total_size);
        
        usleep(500000); // 模拟下载延迟
    }
    return OTA_SUCCESS;
}

// 模拟固件验证
static int mock_verify_firmware(const char *md5)
{
    (void)md5; // 消除未使用参数警告
    
    LOG_INFO("验证固件中...");
    usleep(2000000); // 模拟验证延迟
    
    // 模拟验证成功
    return OTA_SUCCESS;
}

// 模拟固件更新
static int mock_update_firmware(void)
{
    LOG_INFO("更新固件中...");
    usleep(3000000); // 模拟更新延迟
    
    // 模拟更新成功
    return OTA_SUCCESS;
}

void *ota_thread_func(void *arg)
{
    (void)arg; // 未使用的参数
    
    pthread_mutex_lock(&g_ota_mutex);
    g_is_running = true;
    pthread_mutex_unlock(&g_ota_mutex);
    
    LOG_INFO("OTA线程启动");
    
    // OTA线程主循环
    while (g_is_running) {
        pthread_mutex_lock(&g_ota_mutex);
        
        // 等待OTA更新请求
        while (g_is_running && !g_update_in_progress) {
            pthread_cond_wait(&g_ota_cond, &g_ota_mutex);
        }
        
        if (!g_is_running) {
            pthread_mutex_unlock(&g_ota_mutex);
            break;
        }
        
        // 复制OTA信息到局部变量
        ota_info_t local_info = g_current_ota_info;
        pthread_mutex_unlock(&g_ota_mutex);
        
        LOG_INFO("开始OTA更新，版本: %s", local_info.version);
        
        // 更新状态为下载中
        pthread_mutex_lock(&g_ota_mutex);
        g_ota_progress.status = OTA_STATUS_DOWNLOADING;
        g_ota_progress.downloaded_size = 0;
        g_ota_progress.total_size = local_info.file_size;
        pthread_mutex_unlock(&g_ota_mutex);
        
        // 调用回调
        if (g_event_callback) {
            g_event_callback(OTA_STATUS_DOWNLOADING, &g_ota_progress, g_callback_user_data);
        }
        
        // 下载固件
        uint64_t downloaded_size = 0;
        int ret = mock_download_firmware(local_info.url, &downloaded_size, local_info.file_size);
        if (ret != OTA_SUCCESS) {
            LOG_ERROR("下载固件失败: %d", ret);
            
            pthread_mutex_lock(&g_ota_mutex);
            g_ota_progress.status = OTA_STATUS_FAILED;
            g_ota_progress.error_code = ret;
            strncpy(g_ota_progress.error_msg, "下载固件失败", sizeof(g_ota_progress.error_msg) - 1);
            g_update_in_progress = false;
            pthread_mutex_unlock(&g_ota_mutex);
            
            if (g_event_callback) {
                g_event_callback(OTA_STATUS_FAILED, &g_ota_progress, g_callback_user_data);
            }
            continue;
        }
        
        // 更新状态为验证中
        pthread_mutex_lock(&g_ota_mutex);
        g_ota_progress.status = OTA_STATUS_VERIFYING;
        pthread_mutex_unlock(&g_ota_mutex);
        
        if (g_event_callback) {
            g_event_callback(OTA_STATUS_VERIFYING, &g_ota_progress, g_callback_user_data);
        }
        
        // 验证固件
        ret = mock_verify_firmware(local_info.md5);
        if (ret != OTA_SUCCESS) {
            LOG_ERROR("验证固件失败: %d", ret);
            
            pthread_mutex_lock(&g_ota_mutex);
            g_ota_progress.status = OTA_STATUS_FAILED;
            g_ota_progress.error_code = ret;
            strncpy(g_ota_progress.error_msg, "验证固件失败", sizeof(g_ota_progress.error_msg) - 1);
            g_update_in_progress = false;
            pthread_mutex_unlock(&g_ota_mutex);
            
            if (g_event_callback) {
                g_event_callback(OTA_STATUS_FAILED, &g_ota_progress, g_callback_user_data);
            }
            continue;
        }
        
        // 更新状态为更新中
        pthread_mutex_lock(&g_ota_mutex);
        g_ota_progress.status = OTA_STATUS_UPDATING;
        pthread_mutex_unlock(&g_ota_mutex);
        
        if (g_event_callback) {
            g_event_callback(OTA_STATUS_UPDATING, &g_ota_progress, g_callback_user_data);
        }
        
        // 更新固件
        ret = mock_update_firmware();
        if (ret != OTA_SUCCESS) {
            LOG_ERROR("更新固件失败: %d", ret);
            
            pthread_mutex_lock(&g_ota_mutex);
            g_ota_progress.status = OTA_STATUS_FAILED;
            g_ota_progress.error_code = ret;
            strncpy(g_ota_progress.error_msg, "更新固件失败", sizeof(g_ota_progress.error_msg) - 1);
            g_update_in_progress = false;
            pthread_mutex_unlock(&g_ota_mutex);
            
            if (g_event_callback) {
                g_event_callback(OTA_STATUS_FAILED, &g_ota_progress, g_callback_user_data);
            }
            continue;
        }
        
        // 更新状态为完成
        pthread_mutex_lock(&g_ota_mutex);
        g_ota_progress.status = OTA_STATUS_COMPLETED;
        g_update_in_progress = false;
        pthread_mutex_unlock(&g_ota_mutex);
        
        LOG_INFO("OTA更新完成");
        
        if (g_event_callback) {
            g_event_callback(OTA_STATUS_COMPLETED, &g_ota_progress, g_callback_user_data);
        }
    }
    
    LOG_INFO("OTA线程退出");
    return NULL;
}

int ota_init(void)
{
    pthread_mutex_lock(&g_ota_mutex);
    
    if (g_is_initialized) {
        pthread_mutex_unlock(&g_ota_mutex);
        return OTA_SUCCESS;
    }
    
    // 初始化OTA进度
    memset(&g_ota_progress, 0, sizeof(ota_progress_t));
    g_ota_progress.status = OTA_STATUS_IDLE;
    
    LOG_INFO("OTA模块初始化成功");
    g_is_initialized = true;
    
    pthread_mutex_unlock(&g_ota_mutex);
    return OTA_SUCCESS;
}

void ota_cleanup(void)
{
    pthread_mutex_lock(&g_ota_mutex);
    
    if (!g_is_initialized) {
        pthread_mutex_unlock(&g_ota_mutex);
        return;
    }
    
    // 停止OTA线程
    g_is_running = false;
    g_update_in_progress = false;
    pthread_cond_signal(&g_ota_cond);
    
    LOG_INFO("OTA模块清理完成");
    g_is_initialized = false;
    
    pthread_mutex_unlock(&g_ota_mutex);
}

int ota_check_update(ota_info_t *info)
{
    pthread_mutex_lock(&g_ota_mutex);
    
    if (!g_is_initialized) {
        pthread_mutex_unlock(&g_ota_mutex);
        LOG_ERROR("OTA模块未初始化");
        return OTA_ERROR_INIT;
    }
    
    pthread_mutex_unlock(&g_ota_mutex);
    
    // 模拟检查更新
    return mock_check_update(info);
}

int ota_start_update(ota_info_t *info)
{
    pthread_mutex_lock(&g_ota_mutex);
    
    if (!g_is_initialized) {
        pthread_mutex_unlock(&g_ota_mutex);
        LOG_ERROR("OTA模块未初始化");
        return OTA_ERROR_INIT;
    }
    
    if (g_update_in_progress) {
        pthread_mutex_unlock(&g_ota_mutex);
        LOG_WARN("OTA更新已经在进行中");
        return OTA_SUCCESS;
    }
    
    if (!info) {
        pthread_mutex_unlock(&g_ota_mutex);
        LOG_ERROR("OTA信息为空");
        return OTA_ERROR_DOWNLOAD;
    }
    
    // 保存OTA信息
    memcpy(&g_current_ota_info, info, sizeof(ota_info_t));
    g_update_in_progress = true;
    
    // 唤醒OTA线程
    pthread_cond_signal(&g_ota_cond);
    
    pthread_mutex_unlock(&g_ota_mutex);
    
    LOG_INFO("启动OTA更新");
    return OTA_SUCCESS;
}

int ota_cancel_update(void)
{
    pthread_mutex_lock(&g_ota_mutex);
    
    if (!g_is_initialized) {
        pthread_mutex_unlock(&g_ota_mutex);
        LOG_ERROR("OTA模块未初始化");
        return OTA_ERROR_INIT;
    }
    
    if (!g_update_in_progress) {
        pthread_mutex_unlock(&g_ota_mutex);
        LOG_WARN("没有进行中的OTA更新");
        return OTA_SUCCESS;
    }
    
    g_update_in_progress = false;
    g_ota_progress.status = OTA_STATUS_IDLE;
    
    pthread_mutex_unlock(&g_ota_mutex);
    
    LOG_INFO("取消OTA更新");
    return OTA_SUCCESS;
}

int ota_get_progress(ota_progress_t *progress)
{
    pthread_mutex_lock(&g_ota_mutex);
    
    if (!g_is_initialized) {
        pthread_mutex_unlock(&g_ota_mutex);
        LOG_ERROR("OTA模块未初始化");
        return OTA_ERROR_INIT;
    }
    
    if (progress) {
        memcpy(progress, &g_ota_progress, sizeof(ota_progress_t));
    }
    
    pthread_mutex_unlock(&g_ota_mutex);
    return OTA_SUCCESS;
}

int ota_get_current_version(char *version, int max_len)
{
    if (!version || max_len <= 0) {
        LOG_ERROR("参数无效");
        return OTA_ERROR_INIT;
    }
    
    strncpy(version, g_current_version, max_len - 1);
    return OTA_SUCCESS;
}

void ota_register_event_callback(ota_event_cb callback, void *user_data)
{
    pthread_mutex_lock(&g_ota_mutex);
    g_event_callback = callback;
    g_callback_user_data = user_data;
    pthread_mutex_unlock(&g_ota_mutex);
}